package com.hf.template

import groovy.text.Template

import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest

import org.codehaus.groovy.grails.web.context.ServletContextHolder
import org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine
import org.codehaus.groovy.grails.web.servlet.DefaultGrailsApplicationAttributes
import org.springframework.core.io.Resource
import org.springframework.web.context.WebApplicationContext
import org.springframework.web.context.request.RequestAttributes
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.support.WebApplicationContextUtils

import com.hf.application.ApplicationContextHolder

class GspTemplateUtils {

	private static PATH_TO_VIEWS = "/WEB-INF/grails-app/views"

	static String renderTemplate(String templateName, Object model, String pluginName = null) {
		GroovyPagesTemplateEngine groovyPagesTemplateEngine = ApplicationContextHolder.getApplicationContext().getBean(GroovyPagesTemplateEngine)
		if(!groovyPagesTemplateEngine){
			throw new IllegalStateException("Canot find bean 'groovyPagesTemplateEngine'")
		}
		RequestAttributes originalRequestAttributes = RequestContextHolder.getRequestAttributes()
		
		try {
			ServletContext servletContext  = ServletContextHolder.getServletContext()
			WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
			RequestAttributes requestAttributes = grails.util.GrailsWebUtil.bindMockWebRequest(applicationContext)
	
			HttpServletRequest request = requestAttributes.request
	
			DefaultGrailsApplicationAttributes grailsAttributes = new DefaultGrailsApplicationAttributes(servletContext);
			// See if the application has the view for it
			String uri = resolveViewUri(templateName, request)
	
			Resource r = groovyPagesTemplateEngine.getResourceForUri(uri)
	
			// Try plugin view if not found in application
			if ((!r || !r.exists()) && pluginName) {
				// empty
			}
			Template t = groovyPagesTemplateEngine.createTemplate(r)
	
			StringWriter out = new StringWriter();
			requestAttributes.setOut(out)
		
			if(model instanceof Map) {
				t.make(model).writeTo(out)
			} else {
				t.make().writeTo(out)
			}
			return out.toString()
		} finally {
			RequestContextHolder.setRequestAttributes(originalRequestAttributes)
		}
	}

	protected static String resolveViewUri(String viewName, HttpServletRequest request) {
		StringBuffer buf = new StringBuffer(PATH_TO_VIEWS);

		if(viewName.startsWith("/")) {
			String tmp = viewName.substring(1,viewName.length());
			if(tmp.indexOf('/') > -1) {
				buf.append('/');
				buf.append(tmp.substring(0,tmp.lastIndexOf('/')));
				buf.append("/");
				buf.append("_${tmp.substring(tmp.lastIndexOf('/') + 1,tmp.length())}");
			} else {
				buf.append("/");
				buf.append(viewName.substring(1,viewName.length()));
			}
		}
		else {
			if (!request) throw new IllegalArgumentException(
				"View cannot be loaded from relative view paths where there is no current HTTP request")
			DefaultGrailsApplicationAttributes grailsAttributes = new DefaultGrailsApplicationAttributes(request.servletContext);
			buf.append(grailsAttributes.getControllerUri(request))
					.append("/")
					.append(viewName);
		}
		return buf.append(".gsp").toString();
	}
}
